package com.chao.wind3j.base.config.shiroConfig;

import com.chao.wind3j.base.config.commonConfig.CommonProperties;
import com.chao.wind3j.base.config.shiroConfig.advisor.ShiroAdvisor;
import com.chao.wind3j.service.Wind3UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.mgt.SessionStorageEvaluator;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.mgt.DefaultWebSessionStorageEvaluator;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;

@Configuration
public class ShiroConfig {

  @Bean
  @ConditionalOnMissingBean
  public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
    var defaultAAP = new DefaultAdvisorAutoProxyCreator();
    defaultAAP.setUsePrefix(false);
    defaultAAP.setProxyTargetClass(true);
    return defaultAAP;
  }

  @Bean
  public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
    AuthorizationAttributeSourceAdvisor advisor = new ShiroAdvisor();
    advisor.setSecurityManager(securityManager);
    return advisor;
  }

  @Bean
  public JwtRealm jwtRealm(Wind3UserService wind3UserService) {
    return new JwtRealm(wind3UserService);
  }

  @Bean
  public SecurityManager securityManager(Wind3UserService wind3UserService, CommonProperties commonProperties) {
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    securityManager.setRealm(jwtRealm(wind3UserService));
    securityManager.setSubjectDAO(subjectDAO());
    securityManager.setSessionManager(new MySessionManager(commonProperties));
    SecurityUtils.setSecurityManager(securityManager);
    return securityManager;
  }

  @Bean
  public DefaultSubjectDAO subjectDAO() {
    DefaultSubjectDAO defaultSubjectDAO = new DefaultSubjectDAO();
    defaultSubjectDAO.setSessionStorageEvaluator(sessionStorageEvaluator());
    return defaultSubjectDAO;
  }

  @Bean
  public SessionStorageEvaluator sessionStorageEvaluator() {
    DefaultSessionStorageEvaluator sessionStorageEvaluator = new DefaultWebSessionStorageEvaluator();
    sessionStorageEvaluator.setSessionStorageEnabled(false);
    return sessionStorageEvaluator;
  }

  @Bean
  public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager, Wind3UserService wind3UserService, CommonProperties commonProperties) {
    ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
    shiroFilterFactoryBean.setSecurityManager(securityManager);
    var map = new HashMap<String, String>();
    map.put("/**", "jwtFilter");
    map.put("/user/login", "anon");
    map.put("/user/logout", "anon");
    map.put("/swagger-ui.html", "anon");
    map.put("/webjars/**", "anon");
    map.put("/v2/**", "anon");
    map.put("/swagger-resources/**", "anon");
    var filterMap = new LinkedHashMap<String, Filter>();
    filterMap.put("jwtFilter", new JwtFilter(commonProperties, wind3UserService));
    shiroFilterFactoryBean.setFilters(filterMap);
    shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
    return shiroFilterFactoryBean;
  }
}
